import { create } from 'zustand';
import { immer } from 'zustand/middleware/immer';
import { Draft, original, isDraft } from 'immer';
import { redux } from 'zustand/middleware';
import { name } from '@/package.json';
import { toast } from 'sonner';
import { useTemuStore } from './temu';
import type { RegidtrationActivityTableDataItem } from '@/entrypoints/temu-html/RegidtrationActivity';

export interface TemuRegidtrationActivityTask {
  handleTask: () => Promise<void>;
  taskInfo: RegidtrationActivityTableDataItem & {
    id: string | number;
  };
}

export interface QueueItem {
  task: TemuRegidtrationActivityTask;
  resolve?: (result: any) => void;
  reject?: (error: any) => void;
}

function isRepeatTask(total: QueueItem[], newTaskItem: TemuRegidtrationActivityTask) {
  const { id } = newTaskItem.taskInfo;
  // 货号和操作类型相同时才认为是重复任务
  return total.some((queueItem) => queueItem.task.taskInfo.id === id);
}

function processQueue(state: Draft<State>, taskConcurrencyLimit: number, isStopByError: boolean) {
  const concurrent = state.concurrent;
  if (
    concurrent.active.length >= taskConcurrencyLimit ||
    concurrent.queue.length === 0 ||
    concurrent.isStop
  )
    return;

  // 从队列中取出下一个任务
  const nextQueueItem = concurrent.queue.shift();
  // console.log(nextQueueItem);
  const originalQueueItem = isDraft(nextQueueItem) ? original(nextQueueItem) : nextQueueItem;
  let successOriginalQueueItem: QueueItem | null = null;
  let failOriginalQueueItem: QueueItem | null = null;
  if (nextQueueItem) {
    concurrent.active.push(originalQueueItem!);
    const nextQueueId = nextQueueItem.task.taskInfo.id;
    // 执行任务
    const taskPromise = nextQueueItem.task.handleTask();
    taskPromise
      .then((res) => {
        if (originalQueueItem && originalQueueItem.resolve) {
          originalQueueItem.resolve({
            errorCode: 0,
          });
        }
        successOriginalQueueItem = originalQueueItem!;
      })
      .catch((error) => {
        if (originalQueueItem && originalQueueItem.resolve) {
          originalQueueItem.resolve({
            errorCode: 1,
            errorMessage: error.message,
          });
        }
        // console.log(error.message);
        failOriginalQueueItem = originalQueueItem!;
      })
      .finally(() => {
        // console.log(nextQueueItem);
        useTemuNotPersisRegidtrationActivityStore.dispatch({
          type: 'update',
          update(draftState) {
            draftState.concurrent.active = draftState.concurrent.active.filter(
              (queueItem) => queueItem.task.taskInfo.id !== nextQueueId,
            );
            successOriginalQueueItem &&
              draftState.concurrent.success.push(successOriginalQueueItem);
            if (failOriginalQueueItem) {
              draftState.concurrent.fail.push(failOriginalQueueItem);
            }
            if (failOriginalQueueItem && isStopByError) {
              draftState.concurrent.isStop = true;
            }
            processQueue(draftState, taskConcurrencyLimit, isStopByError); // 处理下一个任务
          },
        });
      });
  }
}

const defaultState: State = {
  concurrent: {
    queue: [],
    active: [],
    total: [],
    success: [],
    fail: [],
    isStop: false,
  },
};

interface State {
  concurrent: {
    queue: QueueItem[];
    active: QueueItem[];
    total: QueueItem[];
    success: QueueItem[];
    fail: QueueItem[];
    isStop: boolean;
  };
}

type Actions =
  | {
      type: 'reset';
    }
  | {
      type: 'update';
      update: (draftState: Draft<State>) => void;
    }
  | {
      type: 'clearQueue';
    }
  | {
      type: 'clearAllQueue';
    }
  | {
      type: 'stopTask';
    }
  | {
      type: 'resumeTask';
    }
  | {
      type: 'resumeTaskWithError';
    }
  | {
      type: 'enqueueTask';
      task: TemuRegidtrationActivityTask;
      resolve: (result: any) => void;
      reject: (error: any) => void;
    };

const reducer = (state: Draft<State>, action: Actions) => {
  if (action.type === 'reset') {
    return defaultState;
  }
  if (action.type === 'update') {
    const update = action.update;
    update(state);
  }
  if (action.type === 'clearQueue') {
    const concurrent = state.concurrent;
    // 在 totalTask 队列中移除 queue 相关的任务
    concurrent.total = concurrent.total.filter((item) => {
      return !concurrent.queue.some((task) => task.task.taskInfo.id === item.task.taskInfo.id);
    });
    concurrent.queue = [];
  }
  if (action.type === 'clearAllQueue') {
    const concurrent = state.concurrent;
    concurrent.active = [];
    concurrent.fail = [];
    concurrent.success = [];
    concurrent.queue = [];
    concurrent.total = [];
  }
  if (action.type === 'stopTask') {
    state.concurrent.isStop = true;
  }
  if (action.type === 'resumeTask') {
    const regidtrationActivitySettings = useTemuStore.getState().regidtrationActivitySettings;
    state.concurrent.isStop = false;
    const count =
      regidtrationActivitySettings.taskConcurrencyLimit - state.concurrent.active.length;
    for (let i = 0; i < count; i++) {
      processQueue(
        state,
        regidtrationActivitySettings.taskConcurrencyLimit,
        regidtrationActivitySettings.isStopByError,
      );
    }
  }
  if (action.type === 'resumeTaskWithError') {
    const concurrent = state.concurrent;
    const regidtrationActivitySettings = useTemuStore.getState().regidtrationActivitySettings;
    // 从错误队列中放进待处理队列
    concurrent.queue = [...concurrent.fail, ...concurrent.queue];
    concurrent.fail = [];
    state.concurrent.isStop = false;
    const count =
      regidtrationActivitySettings.taskConcurrencyLimit - state.concurrent.active.length;
    for (let i = 0; i < count; i++) {
      processQueue(
        state,
        regidtrationActivitySettings.taskConcurrencyLimit,
        regidtrationActivitySettings.isStopByError,
      );
    }
  }
  if (action.type === 'enqueueTask') {
    const regidtrationActivitySettings = useTemuStore.getState().regidtrationActivitySettings;
    const newTask: QueueItem = {
      task: action.task,
      resolve: action.resolve,
      reject: action.reject,
    };
    // 如果是重复任何立即返回 resolve 任务完成,这个任务不会计入任何的统计
    if (isRepeatTask(state.concurrent.total, action.task)) {
      action.resolve(void 0);
      return;
    }
    state.concurrent.total.push(newTask);
    state.concurrent.queue.push(newTask);
    // console.log(action.taskConcurrencyLimit);
    processQueue(
      state,
      regidtrationActivitySettings.taskConcurrencyLimit,
      regidtrationActivitySettings.isStopByError,
    );
  }
};

export const useTemuNotPersisRegidtrationActivityStore = create(
  // @ts-expect-error 因为 immer 导致了 reducer 可以返回 undefiend
  immer(redux(reducer, defaultState)),
);

// 持久化处理
export const restoreKey = name + '-temu-regidtration-activity-task';
function handleBeforeUnload(event: BeforeUnloadEvent) {
  if (!restoreKey) {
    return;
  }
  const concurrent = useTemuNotPersisRegidtrationActivityStore.getState().concurrent;
  const restQueue = [...concurrent.active, ...concurrent.queue];
  // console.log(restQueue);
  const taskInfos = restQueue.map((task) => task.task.taskInfo);
  try {
    localStorage.setItem(restoreKey, JSON.stringify(taskInfos));
  } catch (error) {
    toast.error(`localStorage 存储已经到达上限`);
  }
}
window.addEventListener('beforeunload', handleBeforeUnload);
// console.log(window.location.href);

// 每隔 3 秒记录正在处理和待处理的任务,避免浏览器崩溃后无法恢复
// const timmer = setInterval(handleBeforeUnload, 3000);
